package handler

import (
	"context"
	"lab-service/helper"
	ps "lab-service/proto/security"
	"lab-service/security/model"
)

type Security struct{}

func (s *Security) One(ctx context.Context, req *ps.SecurityRequest, rsp *ps.SecurityResponse) error {
	// model Token -> mt
	mt := &model.Token{
		Uid: req.Uid,
	}

	if err := mt.OneByUid(); err != nil {
		return err
	}

	rsp.Role = ps.Role(ps.Role_value[mt.Role])

	return nil
}

func (s *Security) SignJwt(ctx context.Context, req *ps.SecurityRequest, rsp *ps.SecurityResponse) error {
	// model Token -> mt
	mt := &model.Token{
		Uid: req.Uid,
	}

	if err := mt.OneByUid(); err != nil {
		if err := mt.Create(); err != nil {
			return err
		}
	} else if err := mt.ResetToken(); err != nil {
		return err
	}

	var err error
	rsp.Jwt, rsp.Exp, err = helper.SignJwt(req.Uid, req.Remember, mt.Role, mt.RandKey)
	if err != nil {
		return err
	}

	return nil
}

func (s *Security) VerifyJwt(ctx context.Context, req *ps.SecurityRequest, rsp *ps.SecurityResponse) error {
	claim, err := helper.VerifyJwt(req.Jwt)
	if err != nil {
		return err
	}

	if v, ok := claim["role"].(string); ok {
		rsp.Role = ps.Role(ps.Role_value[v])
	}
	if v, ok := claim["uid"].(float64); ok {
		rsp.Uid = int64(v)
	}

	// model Token -> mt
	mt := &model.Token{
		Uid: rsp.Uid,
	}
	if err := mt.OneByUid(); err != nil {
		return err
	}

	if v, ok := claim["rdk"].(string); ok {
		rsp.Rdk = v
	}
	// verify rdk
	if err := mt.CheckRdk(rsp.Rdk); err != nil {
		return err
	}

	return nil
}

func (s *Security) ExpireToken(ctx context.Context, req *ps.SecurityRequest, rsp *ps.SecurityResponse) error {
	// model Token -> mt
	mt := &model.Token{
		Uid: req.Uid,
	}

	if err := mt.OneByUid(); err != nil {
		return err
	}

	if err := mt.ExpireToken(); err != nil {
		return err
	}

	return nil
}
